<template>
  <div style="display: none">
    <slot v-if="ready"></slot>
  </div>
</template>

<script>
import { nextTick, onBeforeUnmount, onMounted, provide, ref } from "vue";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
import { Utilities, Functions, InjectionKeys } from "@vue-leaflet/vue-leaflet";
const { propsBinder, remapEvents, assertInject } = Utilities;
const { setupLayer, render } = Functions.Layer;
const {
  AddLayerInjection,
  RemoveLayerInjection,
  SetParentHtmlInjection,
  CanSetParentHtmlInjection,
} = InjectionKeys;
const { L } = window;
L.Marker.prototype._animateZoom = function (opt) {
  if (this._map) {
    var pos = this._map
      ._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center)
      .round();
    this._setPos(pos);
  }
};
const props = {
  options: {
    type: Object,
    default() {
      return {};
    },
  },
};

export default {
  name: "MarkerCluster",
  props,
  setup(props, context) {
    const leafletRef = ref({});
    const ready = ref(false);

    const addLayerToMainMap = assertInject(AddLayerInjection);
    const removeLayerFromMainMap = assertInject(RemoveLayerInjection);

    provide(CanSetParentHtmlInjection, () => !!leafletRef.value.getElement());
    provide(
      SetParentHtmlInjection,
      (html) => (leafletRef.value.getElement().innerHTML = html)
    );
    // provide('setIcon', (newIcon) => leafletRef.value.setIcon && leafletRef.value.setIcon(newIcon))
    provide(AddLayerInjection, (layer) => {
      leafletRef.value.addLayer(layer.leafletObject);
    });
    provide(RemoveLayerInjection, (layer) => {
      leafletRef.value.removeLayer(layer.leafletObject);
    });

    const { methods } = setupLayer(props, leafletRef, context);
    onMounted(async () => {
      const { DomEvent } = await import("leaflet/dist/leaflet-src.esm");
      const { MarkerClusterGroup } = await import(
        "leaflet.markercluster/dist/leaflet.markercluster-src.js"
      );
      leafletRef.value = new MarkerClusterGroup(props.options);

      const listeners = remapEvents(context.attrs);
      DomEvent.on(leafletRef.value, listeners);

      propsBinder(methods, leafletRef.value, props);

      addLayerToMainMap &&
        addLayerToMainMap({
          ...props,
          ...methods,
          leafletObject: leafletRef.value,
        });

      ready.value = true;
      nextTick(() => context.emit("ready", leafletRef.value));
    });

    onBeforeUnmount(() => {
      const { __gmap } = window;
      if (__gmap.hasLayer(leafletRef.value)) {
        __gmap.removeLayer(leafletRef.value);
      }
      leafletRef.value &&
        leafletRef.value._leaflet_id &&
        removeLayerFromMainMap &&
        removeLayerFromMainMap({ leafletObject: leafletRef.value });
    });

    return { ready, leafletObject: leafletRef };
  },
  render() {
    return render(this.ready, this.$slots);
  },
};
</script>
